﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
using Web7.Core.Security;
using Web7.Core.Security.Users;
using Web7.Domain;
using Web7.Extensions;

namespace Web7.Container.Services
{
    public class DefautlAuthorizationService : IAuthorizationService
    {
        [Dependency]
        public IAssistUserService<Guid> _AssistUserService { get; set; }

        [Dependency]
        public IAssistRoleService<Guid> _AssistRoleService { get; set; }

        [Dependency]
        public IFilterService _FilterService { get; set; }

        [Dependency]
        public IUserRolesPartService _UserRolesPartService { get; set; }

        [Dependency]
        public IMemberShip _MemberShip { get; set; }

        [Dependency]
        public IPermission<Guid> _PermissionProviderService { get; set; }

        public void CheckAccess<T>(Permission permission, IUser user, T content)
        {
            if (!TryCheckAccess<T>(permission, user, content))
            {
                ///TODO;notify
                ///log record
            }
        }

        public void CheckAccess<T>(string permission, IUser user, T content)
        {
            if (!TryCheckAccess<T>(permission, user, content))
            {
                ///TODO;notify
                ///log record
            }
        }

        public bool TryCheckAccess<T>(Permission permission, IUser user, T content)
        {
            if (user == null || user is UserAnonymous) return false;

            var u = user as Entity;
            bool rolePermission = false;
            bool userPermission = false;

            IEnumerable<PermissionRecord> userPermissions = _AssistUserService.GetPermissionsForUser(u.Id);

            IEnumerable<Role> roleMemberOfUser = _MemberShip.GetRoleMemberOfUser(user);

            foreach (var role in roleMemberOfUser)
            {
                role.Permissions = _AssistRoleService.GetPermissionsForRole(role.Id);

                foreach (var p in role.Permissions)
                {
                    if (!p.FilterId.IsNullOrEmpty() && content != null)
                    {
                        rolePermission = CheckPermission(content, p);
                    }
                    else
                    {
                        if (!p.ActionId.IsNullOrEmpty() && permission.Id.Equals(p.ActionId))
                        {
                            rolePermission = true;
                            break;
                        }
                    }
                }
            }

            foreach (var p in userPermissions)
            {
                if (!p.FilterId.IsNullOrEmpty() && content != null)
                {
                    userPermission = CheckPermission(content, p);
                }
                else
                {
                    if (!p.ActionId.IsNullOrEmpty() && permission.Id.Equals(p.ActionId))
                    {
                        userPermission = true;
                        break;
                    }
                }
            }

            if (rolePermission == true)
            {
                if (userPermissions.Any())
                {
                    ///角色有权限，用户没有权限，则用户无权限
                    if (userPermission == false)
                    {
                        return false;
                    }
                }
                ///角色用户都有权限
                return true;
            }
            else
            {
                ///角色无权限，用户有权限，则认为用户有权限
                if (userPermission == true)
                {
                    return true;
                }
                ///角色用户都无权限
                return false;
            }
        }

        public bool TryCheckAccess<T>(string permission, IUser user, T content)
        {
            Permission p = _PermissionProviderService.GetPermissionByName(permission);

            return TryCheckAccess<T>(p, user, content);
        }

        private bool CheckPermission<T>(T content, PermissionRecord p)
        {
            bool checkResult = false;
            IFilter filter = _FilterService.Get(f => f.Id.Equals(p.FilterId));

            switch (filter.FilterType)
            {
                case FilterType.Page:
                    if (content.ToString().IndexOf(filter.ContentFilter) > -1 && !p.ActionId.IsNullOrEmpty())
                    {
                        checkResult = true;
                    }
                    break;
                case FilterType.Tabel:
                    ExpressionContext expressionContent = new ExpressionContext() { Content = content as Entity };
                    IExpressionResolve expressionResolve = new ExpressionResolverService(filter.ContentFilter);
                    expressionResolve.ExpressionContent = expressionContent;
                    checkResult = expressionResolve.ExecuteExpression();
                    break;
                case FilterType.ContentModel:

                    break;
                default:
                    checkResult = false;
                    break;
            }
            return checkResult;
        }
    }
}
